﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Configuration;
using OfficeOpenXml;
using System.Diagnostics;

namespace ExcelFileQueryTool
{
    public partial class frmRecordOnBookSingle : Form
    {
        public string ClientFile { get { return txtFile.Text; } }
        private SimpleFileWatcher _watcher;
        private string _watcherSessionId = Guid.NewGuid().ToString();
        private string _salesYear;
        private string _defaultSheet;

        public string TargetSheetName { get { return this.cboxSheetName.SelectedItem.ToString(); } }

        public frmRecordOnBookSingle(string clientName, string salesYear, string defaultSheet)
        {
            InitializeComponent();

            _salesYear = salesYear;
            _defaultSheet = defaultSheet;
            this.lblClientName.Text = clientName;
            FindClientFile(clientName);
        }

        private void FindClientFile(string clientName)
        {
            var sourceClientName = AppConfig.GetSourceName(clientName);
            var files = Directory.GetFiles(AppConfig.SourceFolder, String.Format("[对数表]*{0}*.xlsx", sourceClientName), SearchOption.AllDirectories);

            if (files == null || files.Count() == 0)
            {
                files = Directory.GetFiles(AppConfig.SourceFolder, AppConfig.FilePattern, SearchOption.AllDirectories);

                var targetFiles = new List<string>();

                foreach (var f in files)
                {
                    var fn = ClientFileService.GetClientNameFromFile(f);
                    var sv = LevenshteinDistance.GetSimilarity(fn, sourceClientName);

                    if (sv >= 0.4m)
                        targetFiles.Add(f);
                }

                ShowFileSelectionGrid(targetFiles.Where(x => AppConfig.ExcludeFileNames.All(y => !x.EndsWith(y))));
            }
            else if (files.Length == 1)
            {
                txtFile.Text = files[0];
            }
            else
            {
                // 在这里做精确匹配，是为了避免过多的IO操作。如果放在方法的开头做，则需要进行两次GetFiles操作。
                var expectedFile = String.Format("[对数表]{0}.xlsx", sourceClientName);
                var targetFile = files.FirstOrDefault(x => x.EndsWith(expectedFile));

                if (targetFile != null)
                    txtFile.Text = targetFile;
                else
                    ShowFileSelectionGrid(files.Where(x => AppConfig.ExcludeFileNames.All(y => !x.EndsWith(y))));
            }
        }

        private void ShowFileSelectionGrid(IEnumerable<string> files)
        {
            if (files == null || files.Count() == 0)
                return;

            files = files.OrderByDescending(x => x);

            var dgv = new DataGridView();
            dgv.Name = "dgvFiles";
            dgv.Location = new Point(10, this.Bottom);
            dgv.Width = this.ClientRectangle.Width - 30;
            dgv.Height = 150;
            dgv.BackgroundColor = Color.AliceBlue;
            dgv.AutoGenerateColumns = false;
            dgv.AllowUserToAddRows = false;
            dgv.AllowUserToDeleteRows = false;
            dgv.AllowUserToOrderColumns = false;
            dgv.AllowUserToResizeRows = false;
            dgv.EditMode = DataGridViewEditMode.EditProgrammatically;
            dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;
            dgv.Columns.Add("file", "文件名");
            dgv.Columns.Add(new DataGridViewButtonColumn { Text = "选择", HeaderText = "操作", UseColumnTextForButtonValue = true });

            foreach (var f in files)
            {
                var row = new DataGridViewRow();
                row.Cells.Add(new DataGridViewTextBoxCell
                {
                    Value = Path.GetFileNameWithoutExtension(f).Replace("[对数表]", string.Empty),
                    ToolTipText = f
                });

                dgv.Rows.Add(row);
            }

            dgv.CellClick += (sender, e) =>
            {
                if (e.RowIndex < 0)
                    return;

                if (e.ColumnIndex != 1)
                    return;

                var grid = (DataGridView)sender;
                var selectedFile = grid[0, e.RowIndex].ToolTipText.ToString();
                this.txtFile.Text = selectedFile;
            };

            this.Height += (dgv.Height + 45);
            this.Controls.Add(dgv);
        }

        private void btnCancle_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(this.ClientFile) || _watcher == null)
                return;

            if (_watcher.FileHasChanged)
            {
                LoadSheets();
                MessageBox.Show("检测到文件变动，已重新加载数据，请重新确定保存参数！", "客户记录保存准备操作", MessageBoxButtons.OK);

                return;
            }

            this.DialogResult = DialogResult.OK;
            this.Close();
        }

        private void btnChoose_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog diag = new OpenFileDialog())
            {
                diag.Filter = AppConfig.ClientFileChooseFilter;

                if (diag.ShowDialog(this) == DialogResult.OK)
                    txtFile.Text = diag.FileName;
            }
        }

        private void txtFile_TextChanged(object sender, EventArgs e)
        {
            _watcher = new SimpleFileWatcher(this.ClientFile, _watcherSessionId);
            LoadSheets();
        }

        private void LoadSheets()
        {
            cboxSheetName.Items.Clear();

            if (File.Exists(txtFile.Text) == false)
                return;

            using (ExcelPackage package = new ExcelPackage(new FileInfo(this.txtFile.Text)))
            {
                foreach (var sheet in package.Workbook.Worksheets)
                {
                    if (sheet.IsConclusionSheet() || sheet.IsHistorySheet())
                        continue;

                    if (sheet.IsDataSheet())
                        cboxSheetName.Items.Add(sheet.Name);
                }
            }

            _defaultSheet = cboxSheetName.Items.Cast<string>().FirstOrDefault(x => LevenshteinDistance.GetSimilarity(_defaultSheet, x) > 0.6m);

            if (string.IsNullOrEmpty(_defaultSheet))
                cboxSheetName.SelectedIndex = 0;
            else
                cboxSheetName.SelectedItem = _defaultSheet;

            _watcher.UpdateModifiedTime(_watcherSessionId);
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            string f = this.txtFile.Text;
            if (string.IsNullOrWhiteSpace(f))
                return;

            using (Process.Start(f)) { }
        }

        private void btnCreateClientFile_Click(object sender, EventArgs e)
        {
            //todo: 新增sheet的功能

            using (var f = new frmCreateClientFile(lblClientName.Text.Trim(), type: "散客", salesYear: _salesYear))
            {
                if (f.ShowDialog() == DialogResult.OK)
                    this.txtFile.Text = f.ClientFile;
            }
        }

        private void lblRefresh_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            LoadSheets();
        }

        private void cboxSheetName_SelectedIndexChanged(object sender, EventArgs e)
        {
            // 检测最后一行记录并显示简单信息，用于保存前后的校验
            if (cboxSheetName.SelectedIndex < 0)
                return;

            var sheetName = cboxSheetName.SelectedItem.ToString();

            using (ExcelPackage p = new ExcelPackage(new FileInfo(txtFile.Text)))
            {
                var sheet = p.Workbook.Worksheets[sheetName];
                var rowIndex = sheet.Dimension.End.Row - 1; // there is a total row

                // 没有空行
                if (string.IsNullOrWhiteSpace(sheet.Cells[rowIndex, DataSheetColumnIndex.Product].GetValue<string>()) == false)
                {
                    rowIndex++;
                }
                else
                {
                    // at least there is a header row
                    while (rowIndex > 1)
                    {
                        // 可能最后一行的日期列是合并单元格，所以用货物列作为判断依据可以保证准确性
                        if (sheet.Cells[rowIndex - 1, 1].Merge
                            || string.IsNullOrWhiteSpace(sheet.Cells[rowIndex - 1, DataSheetColumnIndex.Product].GetValue<string>()) == false)
                            break;

                        rowIndex--;
                    }
                }

                var lastDataRowIndex = rowIndex - 1;
                var date = sheet.Cells[lastDataRowIndex, 1].Text;
                if (string.IsNullOrEmpty(date))
                    date = "--";

                string lastRowContent = string.Format("[{0},{1},{2}{3}{4}]"
                           , lastDataRowIndex
                           , date
                           , sheet.Cells[lastDataRowIndex, DataSheetColumnIndex.Product].GetValue<string>()
                           , sheet.Cells[lastDataRowIndex, DataSheetColumnIndex.Amount].GetValue<string>()
                           , sheet.Cells[lastDataRowIndex, DataSheetColumnIndex.Unit].GetValue<string>());

                lblNote.Text = "注意：目前最后一行数据为" + lastRowContent + "，请注意入账后进行校验！";
            }
        }

        /// <summary>
        /// 保证更改文件后自动更新界面
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmRecordOnBookSingle_Enter(object sender, EventArgs e)
        {
            LoadSheets();
        }
    }
}
